#pragma once
#include <poll.h>
#include "socket_server.h"

#define default_port 8888

static int sz = 1024;

class Poll
{
public:
    Poll(uint16_t port = default_port)
        : _tcp_socket(make_unique<Tcp>(port)), _port(port), _inode(0)
    {
        _rfds = new pollfd[sz]; // 开辟空间,表明起初可以承载文件描述符的数量
        // 后期也可以空间不够动态扩容
    }

    void Init()
    {
        _tcp_socket->Creat_socket();
        _tcp_socket->Bind();
        _tcp_socket->Listen();

        // 初始化_rfds
        for (int i = 0; i < sz; i++)
        {
            _rfds[i].fd = -1;
            _rfds[i].events = _rfds[i].revents = 0;
        }

        // 将需要进行poll的监听套接字直接添加进来
        _rfds[_inode].fd = _tcp_socket->Get_sockfd();
        _rfds[_inode].events |= POLLIN; // 新连接到来属于可读事件POLLIN
        _inode++;
    }

    void Run()
    {
        while (true)
        {
            int n = poll(_rfds, _inode, 3000); // 3000ms,为-1表示阻塞等待

            switch (n)
            {
            case 0:
                cout << "poll timeout, retrying..." << endl;
                break;

            case -1:
                cerr << "poll erro...poll一个已经关闭的文件描述符" << endl;
                break;

            default: // n>0(n个文件描述符状态发生变化)
                cout << "poll success..." << endl;
                Handler_poll();
                break;
            }
        }
    }

    ~Poll()
    {
        delete[] _rfds;
    }

private:
    unique_ptr<Tcp> _tcp_socket;
    uint16_t _port;
    struct pollfd *_rfds;
    nfds_t _inode; // typedef unsigned long nfds_t

private:
    void Handler_poll()
    {
        for (int i = 0; i < _inode; i++)
        {
            pollfd cur = _rfds[i];

            if (cur.revents & POLLIN) // 当前的pollfd(读事件)事件就绪
            {
                // 读事件分两类：1.新连接 2.新数据

                if (cur.fd == _tcp_socket->Get_sockfd()) // 1.获取新的连接
                {
                    uint16_t connect_sockfd = _tcp_socket->Accept();
                    cout << "get a newsockfd: " << connect_sockfd << endl;

                    // 将新的connect套接字描述符添加到pollfd中
                    if (_inode < sz)
                    {
                        _rfds[_inode].fd = connect_sockfd;
                        _rfds[_inode].events |= POLLIN;
                        _inode++;
                    }
                    else // 数组达到上限了
                    {
                        sz += 512;
                        pollfd *newrfds = new pollfd[sz];
                        memcpy(newrfds, _rfds, sizeof(pollfd) * (sz - 512));
                        delete[] _rfds;
                        _rfds = newrfds;
                    }
                }
                else // 2.收到数据
                {
                    string buffer;
                    bool ret = _tcp_socket->Recv(cur.fd, buffer, 1024);
                    if (!ret)
                    {
                        cerr << "读取失败..." << endl;

                        // 取消poll的关心
                        cur.fd = -1;    // 关闭的文件描述符置为-1
                        cur.events = 0; // 读取时间置为0
                        close(cur.fd);
                    }
                    else
                    {
                        cout << "client say: " << buffer << endl;
                        string repo = "hello:" + buffer;
                        send(cur.fd, repo.c_str(), repo.size(), 0);
                        buffer.clear();
                    }
                }
            }
            else
            {
                cout << "当前无事件就绪..." << endl;
            }
        }
    }
};